/*
  开始时间：2016.8.4
  目的： xu-1.0.js升级版,优化大部分代码
  制作人： xu
  新增内容： queue，callback，deferred，ajax，animate
  去除模块： carousel旋转木马轮播
  结束时间： 2016.8.10
*/ 

;(function(window,undefined){

  //id规则
  var idExp = /^\s*\#/;

  // html字符串规则,如：<div>
  var htmlExp = /^\s*<(\w+)>/;

  var indexOf = Array.prototype.indexOf;

  var Xu = function(selector,context) {
    return new Xu.fn.init(selector,context);
  }

  Xu.version = '1.1';

  Xu.fn = Xu.prototype = {

    constructor : Xu,
    // 只针对单选择器或后代选择器
    init: function(selector,context) {

      if(!selector) {
        return this;
      }
      // 如果是对象直接返回
      if(selector.nodeType) {
        this.context = this[0] = selector;
        this.length = 1;
        return this;
      }
      
      // 如果是字符串是body直接返回
      if( selector === 'body' && !context && document.body) {
        this.context = document;
        this.selector = selector;
        this[0] = document.body;
        this.length = 1;
        return this;
      }
      // 如果是普通字符串
      if(typeof selector === 'string') {

        // 去掉收尾空格
        selector = Xu.trim(selector);

        if(selector.indexOf('<') > -1 && selector.length > 3 ) {
          // 创造dom对象并返回jq对象
          this[0] = Xu.parseHTML(selector);
          this.length = 1;
          this.context = document;
        }else {

          var selectList = selector.split(/\s+/);

          if(idExp.test(selectList[0])) {
            // 如果只有一个id选择器，那么context便是document，否则是id对应对象
            this.context = selectList[1] ? Xu.id( selectList[0].substring(1) ) : document;

            this.selector = selectList[0];
            selectList = selectList.slice(1);

          }else {
            this.selector = '';
            this.context = document;
          }
          this[0] = this.context;
          this.length =1;
          // 如果没有选择器了，就返回this
          if(!selectList.length) return this;

          this.find(selectList, context);

        }
        
        // 如果是函数，加载
      }else if(Xu.isFunction(selector)) {
        Xu.ready(selector);
      }
      return this;
    }

  }

  //对象继承
  Xu.extend = Xu.fn.extend = function() {
    var target, copy , id,i =1,midd ;
    target = arguments[0] || {}
    if( arguments.length == i ) {
      target = this;
      i--;
    }
    for(; i < arguments.length ; i++) {
      midd = arguments[i];
      for(id in midd) {
        copy = midd[id];
        target[id] = copy;
      }
    }
    return this;
  }


  //加载页面
  Xu.ready = function(func) {
    if( Xu.isIE() ) {     //ie的方法
      var timer = null;
      timer = setInterval(function(){
        try{
          document.documentElement.doScroll('left');
          func();
        }catch(e){}
      },1);
    }else {
      document.addEventListener('DOMContentLoaded',func,false);
    }
  }

  // dom查询
  Xu.fn.extend({

    find: function(selectList,context) {
      if(typeof selectList === 'string') {

        selectList = Xu.trim(selectList).split(/\s+/);
      }
      var  parents = [],nodeList=[],nodes=[],sel,
        oldLen = this.length,len , i,j,k;

      for(i = 0 ; i < oldLen; i++) {
        parents[i] = this[i];
      }

      this.context = context || parents[0];
      // 循环选择器数组
      for(i=0 ;i<selectList.length; i++) {
        sel = selectList[i];
        // 没find一次添加一次selector层次
        this.selector += ' '+sel;

        nodeList = [];
        // 遍历dom
        for(j=0; j<parents.length; j++) {
          nodes = sel.charAt(0) === '.' ?  Xu._class(sel.substring(1),parents[j]):
            Xu._tag(sel,parents[j]);

          for(k=0; k< nodes.length; k++ ) {
            nodeList.push(nodes[k]);
          }
        }
        parents = nodeList;
      }
      len = nodeList.length;
      // 清楚原来的dom
      for(i=0; i<oldLen; i++) {
        this[i] = undefined;
      }
      if( !len ) {
        this.length = 0;
        
      }else {
        this.length = len;
        for(i=0; i<len; i++) {
          this[i] = nodeList[i];
        }
      }

      return this;
    },
    eq : function(index) {
      this.selector += ' eq('+index+')';
      return this.slice(index,index+1);
    },
    slice: function(start,end) {
      // 新建一个Xu对象并返回。
      return Xu.createStack(this,start,end);
    },
    get : function(index) {
      return this[index];
    },
    getAll:function() {
      return Xu.createStack(this,0,this.length);
    },
    first: function() {
      this.selector += ':first';
      return this.slice(0,1);
    },
    last: function() {
      this.selector += ':last';
      return this.slice(this.length-1,this.length)
    },
    next: function() {
      var i, copy;
      this.selector += ':next';
      for(i=0; i<this.length; i++) {
        copy = this[i];
        copy = copy.nextSibling;
        while(copy.nodeType == 3) {
          copy = copy.nextSibling;
        }
        this[i] = copy;
      }
      return this;
    },
    prev: function() {
      var i, copy;
      this.selector += ':prev';
      for(i=0; i<this.length; i++) {
        copy = this[i];
        copy = copy.previousSibling;
        while(copy && copy.nodeType == 3) {
          copy = copy.previousSibling;
        }
        this[i] = copy;
      }
      return this;
    },
    children: function() {
      var i,ret = Xu(), index=0,
        childNodes = [], n;
      // 新对象属性赋值
      ret.selector = this.selector+':children';
      ret.context = this.context;
      // 查找dom
      for(i=0; i<this.length; i++) {
        childNodes = this[i].children;

        for(n=0; n<childNodes.length; n++) {
          ret[index++] = childNodes[n];
        }
      }
      ret.length = index;
      return ret;
    },
    siblings:function() {

      var ret = $(), i=0, j, len=0, 
        childList=[], aChild;

      ret.selector = this.selector +':siblings';
      ret.context = this.context;

      for(; i<this.length; i++) {
        childList = this[i].parentNode.children;

        for(j=0; j<childList.length; j++) {
          aChild = childList[j];

          if(aChild !== this[i]) {
            ret[len++] = aChild;
          }

        }
      }
      ret.length = len; 
      return ret;
    }

  })

  // dom添加删除
  Xu.fn.extend({
    appendTo: function(selector) {

      if(typeof selector !== 'string') return;

      var ret = Xu(selector);

      ret.append(this[0]);
          
      return this;

    },
    append: function(dom) {

      if(!dom.nodeType) {
        dom = Xu.parseHTML(dom);
      }

      for(var i=0; i<this.length; i++) {
        this[i].appendChild(dom);
      }

      return this;

    },
    prevpend: function(dom) {
      if(!dom.nodeType) {
        dom = Xu.parseHTML(dom);
      }

      for(var i=0; i<this.length; i++) {
        this[i].insertBefore(dom,this[i].firstChild );
      }

      return this;
    },
    prevpendTo(selector) {
      if(typeof selector !== 'string') return;

      var ret = Xu(selector);

      ret.prevpend(this[0]);

      return this;
    },
    remove: function() {
      var elem;
      for(var i=0; i<this.length; i++) {
        elem = this[i];
        elem.parentNode.removeChild(elem);
      }
      return this;
    },
    empty: function() {
      for(var i=0; i<this.length; i++) {
        this[i].innerHTML = '';
      }
      return this;
    }
  })


  //Xu对象中的dom操作方法
  Xu.fn.extend({
    html : function(str) {
      if( str === undefined ) {
        return this[0].innerHTML;
      }
      for(var i=0; i<this.length; i++) {
        var elem = this[i]
        if (typeof str === 'object') {
          //  传递Xu对象的时候
          $.map(str,function (item, index) {
            elem.appendChild(item)
          })
        } else {
          elem.innerHTML = str;
        }
        
      }
      return this;
    },
    text : function(str) {
      if(str === undefined) {
        return this[0].textContent || this[0].innerText;
      }
      for(var i=0; i<this.length; i++) {
        this[i].innerText = this[i].textContent = str;
      }
      return this;
    },
    attr : function(key,value) {
      if(value === undefined) {
        return this[0].getAttribute(key);
      }
      for(var i=0; i<this.length; i++) {
        this[i].setAttribute(key,value);
      }
      return this;
    },
    val:function(value) {  
      // 没考虑checkbox和radio
      if(value === undefined) {
        return this[0].value;
      }
      for(var i=0; i<this.length; i++) {
        this[i].value = value;
      }
      return this;
    },
    hasClass: function(str) {
      return Xu.hasClass(this[0],str);
    },
    addClass: function(str) {
      for(var i=0; i<this.length; i++) {
        Xu.addClass(this[i],str);
      }
      return this;
    },
    removeClass:function(str) {
      for(var i=0; i<this.length; i++) {
        Xu.removeClass(this[i],str);
      }
      return this;
    },
    toggleClass: function(str) {
      var elem;
      for(var i=0; i<this.length; i++) {
        elem = this[i];
        if( new RegExp('(\\s+|^)'+str+'(\\s+|$)').test(elem.className) ) {
          Xu.removeClass(elem,str);
        }else {
          Xu.addClass(elem,str);
        }
      }
      return this;
    }
  })




  Xu.extend({
    // 清除和创建对象
    cleaStack : function(obj) {
      for(var i=0; i<obj.length; i++) {
        delete obj[i];
      }
    },
    createStack: function(obj,start,end) {
      var ret = $();
      for(var i=start; i<end; i++) {
        $.push(ret,obj[i]);
      }
      return ret;
    },
    push: function (obj, elem) {
      if (!obj.length) {
        obj.length = 0;
      }
      obj[obj.length++] = elem
    },
    // 兼容性事件绑定和删除
    addEvent:function(obj,type,fun) {
      function addEvent(obj,type,fun){
        if( typeof obj.addEventListener != 'undefined' ){
          return obj.addEventListener(type,fun, false);
        }else{
          if( !obj.events ) obj.events = {};
          if( !obj.events[type] ){
            obj.events[type] = [];
            if( obj['on' + type] ) obj.events[type][0].fun;
          }else{
            if ( this.equal(obj.events[type], fun) ) return false;
          }
          obj.events[type][this.ID++] = fun;
          obj['on'+type] = this.exec;
        }
      }
      addEvent.prototype ={
        ID : 1,
        exec : function(event){
          var e = event || this.fixEvent(window.event);
          var es = this.events[e.type];
          for(var g in es) es[g].call(this,e);
        },
        equal : function(es , fun){
          for(var i in es){
            if(es[i] == fun) return true;
          }
          return false;
        },
        fixEvent : function(event){
          event.preventDefault = this.fixEventPreventDefault;
          event.stopPropagation = this.fixEventStopPropagation;
          event.target = event.srcElement;
          return event;
        },
        fixEventPreventDefault : function(){
          this.returnValue = false;
        },
        fixEventStopPropagation : function(){
          this.cancelBubble = true;
        }
      }
      new addEvent(obj,type,fun);
    },
    removeEvent:function(obj,type,fun) {
      if( typeof obj.removeEventListener != 'undefined' ){
        return obj.removeEventListener(type,fun ,false);
      }else if( obj.event ){
        for( var i in obj.events[type] ){
          if( obj.events[type][i] == fun ) delete obj.events[type][i];
        }
      }
    },
  })




  //each方法
  Xu.each = function(obj,func) {
    for(var i=0; i<obj.length; i++) {
      func.call(obj[i],obj[i],i);
    }
    return obj;
  }
  Xu.fn.each = function(func) {
    
    return Xu.each(this,func);
  }


  //Xu对象 对css的操作
  Xu.fn.extend({
    css : function(attr,value) {
      var i,len=this.length;
      if(typeof attr === 'string') {
        if( value === undefined ) {
          return Xu.getStyle(this[0],attr);
        }else {
          for(i=0; i<len; i++) {

            this[i].style[attr] = value;
          }
        }
      }else if(typeof attr === 'object') {
        for(i=0; i<len; i++) {
          for(var key in attr ) {
            this[i].style[key] = attr[key];
          }
        }

      }
      return this;
    },
    color: function(val) {
      if(val === undefined) {
        return Xu.getStyle(this[0],'color');
      }
      for(var i=0; i<this.length; i++) {
        this[i].style.color = val;
      }
      return this;
    },
    bgColor: function(val) {
      if(val === undefined) {
        return Xu.getStyle(this[0],'backgroundColor');
      }
      for(var i=0; i<this.length; i++) {
        this[i].style.backgroundColor = val;
      }
      return this;
    },
    show : function() {
      if( Xu.getStyle(this[0],'display') === 'none' ) {
        for(var i=0; i<this.length; i++) {
          this[i].style.display =  Xu.data(this[i],'display') || '';
        }
      }
      return this;
    },
    hide: function() {
      for(var i=0; i<this.length; i++) {
        Xu.data(this[i], 'display' ,Xu.getStyle(this[i],'display'));
        this[i].style.display = 'none';
      }
      return this;
    },
    height: function(val){
      if(val === undefined) {
        return parseInt( Xu.getStyle(this[0],'height') );   
      }else{
        if(+val >= 0){
          for(var i=0; i<this.length; i++) {
            this[i].style.height = val+'px';
          }
        }else {
          throw '参数错误！';
        }
      } 
      return this;
    },
    width: function(val){
      if(val === undefined) {
        return parseInt( Xu.getStyle(this[0],'width') );    
      }else{
        if(+val >= 0){
          for(var i=0; i<this.length; i++) {
            this[i].style.width = val+'px';
          }
        }else {
          throw '参数错误！';
        }
      } 
      return this;
    },
    offset:function(){
      return { 
        width : this[0].offsetWidth,
        height : this[0].offsetHeight,
        left : this[0].offsetLeft,
        top : this[0].offsetTop
      }
    }


  });



  // 判断
  Xu.extend({
    isFunction: function(some) {
      return some && typeof some === 'function' && some instanceof Function &&
        Object.prototype.toString.call(some) == '[object Function]';
    },
    isArray: function(arr) {
      return arr && typeof arr === 'object' && arr instanceof Array && 
        Object.prototype.toString.call(arr) == '[object Array]';
    },
    isEmpty: function(obj) {
      for(var key in obj) {
        return false;
      }
      return true;
    }
  })

  // 内部工具
  Xu.extend({
    _id: function(id) {
      return document.getElementById(id);
    },
    _tag: function(tag,parent) {
      if( !parent ) parent = document;
      return parent.getElementsByTagName(tag);
    },
    _class:function(clas,parent) {

      parent = parent || document;
      if(document.getElementsByClassName) {
        return parent.getElementsByClassName(clas);
      }
      var all = Xu.tag('*',parent) , elem=[];

      for(var i=0,len=all.length; i<len; i++) {
        if( all[i].className.indexOf(clas) != -1) {
          elem.push(all[i]);
        }
      }
      return elem;
    },
    trim : function(str) {
      return str.replace(/(^\s*)|(\s*$)/g,'');
    },
    isIE:function() {
      return !-[1,];
    },
    hasClass : function(elem,str) {
      return elem.className.indexOf(str) === -1 ? false:true;
    },
    addClass: function(elem,str) {
      if(!Xu.hasClass(elem,str) ) {
        elem.className += ' '+str;
      }
    },
    removeClass:function(elem,str) {
      elem.className = elem.className.replace(str,'');
    },
    getStyle : function(elem,attr) {
      return window.getComputedStyle ? getComputedStyle(elem,null)[attr] : elem.currentStyle[attr];
    },
    createElement:function (tag){
      var elem = document.createElement(tag);
      return elem;
    },
    map: function(obj,func, context) {

      if( [].map ) {
        [].map.call(obj, func);
      }else {
        for(var i=0; i< obj.length; i++) {
          func.call(context || null,obj[i],i);
        }
      }
    },
    stringify: function(data) {
      var str = '';
      if( !data || Xu.isEmpty(data)) {
        return str;
      }
      for(var key in data) {
        str += key + '='+ data[key]+'&'
      }
      str = str.slice(0,-1);
      return str;
    },
    parseJSON : function(text) {
      if(typeof text !== 'string') {
        return;
      }
      if( JSON && JSON.parse ) {
        return JSON.parse(text);
      }
      return (new Function('return '+text))();
    },
    parseHTML: function(html) {
      // 获取dom名称正则
      var nodeNamePatt = /^<(\w+)[\s|>]/,
        // 获取dom开始标签的内容
        nodeLabelContentPatt = /^<[\w\:\;\s\=\'\"\-]+>/,
        // 获取dom属性和值的内容
        nodeAttributePatt = /\s+(\w+)=[\'|\"]([\w\:\;\s\-]+)[\'|\"]/g,
        // 获取dom内的文本
        nodeTextPatt = />([\w|\W]+)</,
        // 存放属性的键值对的数组
        attrs = [],attr,

        nodeText = nodeTextPatt.exec(html) && nodeTextPatt.exec(html)[1] || '',

        nodeName = nodeNamePatt.exec(html)[1],

        nodeLabelContent = nodeLabelContentPatt.exec(html)[0],

        nodeAttribte;
        // 遍历查找属性
        while( nodeAttribte = nodeAttributePatt.exec(nodeLabelContent) ) {
          attr = {
            key: nodeAttribte[1],
            value: nodeAttribte[2]
          };
          attrs.push(attr);
        }
        // 返回新建的dom对象
        return Xu.createHtmlDom(nodeName,nodeText,attrs);

    },
    now: function() {
        return +new Date();
    },
    createHtmlDom: function(name,text,attrs) {
      var i, attr,
        node = document.createElement(name),

        text;

        if(!attrs && typeof text === 'object') {
          attrs = text;
          text = null;
        }
        
        if(text && typeof text === 'string') {
          text = document.createTextNode(text);
          node.appendChild(text);
        }

        if(attrs) {
          for(i=0; i<attrs.length; i++) {
            attr = attrs[i];
            node.setAttribute(attr.key,attr.value);
          }
        }
        return node;

    }
    
  })
  
  //外部窗口公共方法
  Xu.extend({
    center : function(target){
      var screen_width = document.documentElement.clientWidth;
      var screen_height = document.documentElement.clientHeight;
      for(var i = 0; i < target.length; i++){

        var elem = target[i];
        //alert(elem)
        var width = parseInt(Xu.getStyle(elem,'width'));
        var height = parseInt( Xu.getStyle(elem,'height') );
        if( Xu.getStyle(elem,'position') === 'static'){
          elem.style.position = 'fixed';
        }
        elem.style.top = (screen_height - height)/2 + 'px';
        elem.style.left = (screen_width - width)/2 +'px';
      }
    },
    stopScroll:function() {
      document.documentElement.scrollTop = 0;
      document.body.scrollTop = 0;
    },
    resize: function(func) {
      var self = this;
      Xu.addEvent(window,'resize',function() {
        func.call(self)
      });
    },
    lock : function(elem,zIndex){
      if( zIndex === undefined ){
        zIndex = elem;
        elem = Xu.parseHTML('<div class="xu-locked">');
        document.body.appendChild(elem);
      }
      var width = window.innerWidth ? window.innerWidth + 'px' : 
            document.documentElement.clientWidth + 'px';
      var height = window.innerHeight ? window.innerHeight + 'px' :
             document.documentElement.clientHeight + 'px';
      Xu(elem).css({
        height: height,
        width: width,
        display: 'block',
        position: 'fixed',
        backgroundColor: '#ccc',
        top: 0,
        left: 0,
        zIndex: zIndex
      })
      //    在遮罩时屏幕不可改变大小
      Xu.addEvent(window , 'scroll' ,Xu.stopScroll );
    },
    unlock:function(elem){
      if( !elem ){
        elem = Xu._class('xu-locked')[0];
      }
      elem.style.display = 'none';
      Xu.removeEvent(window,'scroll', Xu.stopScroll);
    }
  })

  //对象中的 窗口事件
  Xu.fn.extend({
    center : function(){
      Xu.center(this);
      return this;
    },
    resize: function(func) {   
      Xu.resize(func)
      return this;
    },
    lock:function(zIndex) {
      zIndex = zIndex || '8';
      Xu.lock(this[0],zIndex);
      return this;
    },
    unlock:function(){
      Xu.unlock(this[0]);
      return this;
    }

  })


  // 事件部分

  Xu.fn.extend({
    on : function(type,func) {
      for(var i=0; i<this.length; i++) {
        Xu.addEvent(this[i],type,func);
      }

      return this;
    },
    off:function(type,func) {
      for(var i=0; i<this.length; i++) {
        Xu.removeEvent(this[i],type,func);
      }
      return this;
    }
  })

  Xu.each(['click','mouseover','mouseout','mouseenter','mouseleave','mousedown','mouseup',
    'mousemove','keydown','keyup','focus','blur'],function(type) {
    Xu.fn[type] = function(func) {
      for(var i=0; i<this.length; i++) {
        Xu.addEvent(this[i],type,func);
      }
      return this;
    }
  })

  // 速度规则
  var speed ={
    'slow' : 800,
    'normal' : 500,
    'fast' : 200
  }
  // 扩展事件
  Xu.fn.extend({
    fadeTo: function(value,time,func) {

      if(typeof value !== 'number') return;

      // 如果是用英文单词表示，那么就变成相应的时间
      if(typeof time === 'string') {
        time = speed[time];
      }
      time = time || 500;

      return this.animate({opacity:value},time,func);

    },
    fadeIn: function(time,func) {

      return this.fadeTo(100,time,func);
    },
    fadeOut: function(time,func) {
      return this.fadeTo(0,time,func);
    },
    toggle: function(funcOne,funcTwo) {
      // 显示隐藏切换
      if(arguments.length == 0) {
        if( this.css('display') === 'none' ) {
          return this.show();
        }else {
          return this.hide()
        }
      }

      if(typeof funcOne !== 'function') return;
      // 一个函数
      if(!funcTwo) {
        return this.on('click',funcOne);
      }
      // 两个函数
      return this.on('click', function() {

        // 缓存对象this
        if(!this.nameIndex) {
          this.nameIndex = 'toggle' + (Math.random()).toString().slice(2,7);
          this.num = 0;
        }

        this.num = Xu.data(this,this.nameIndex,++this.num);
        
        (this.num%2 === 0? funcTwo : funcOne).call(this)

       
      })
    }

  })




  // data缓存
  // 结构：
  /*
  {
    object: [
      {
        name: 'xu'
      },
      {
        age: 21
      }
    ]
  }*/

  Xu.extend({
    // 缓存对象
    cache: {},

    data: function(elem,name,data) {
      if( !elem.nodeType && typeof elem !== 'object' ) {
        return;
      }
      var prevCache = Xu.cache[elem];
      if(arguments.length === 2) {
        return  prevCache && prevCache[name];
      }
      // 添加或更新cache
      if(!prevCache) {
        Xu.cache[elem] = new Object();
        Xu.cache[elem][name] = data;
      }else {
        prevCache[name] = data;
      }
      return data;
    }

  })





  // callback机制

  Xu.Callback = function(option) {
     // 存放函数的列表
  var list = [];

  /*3种状态常量*/

  // 默认方式
  var MODE_DEFAULT = undefined;
  
  // once方式，只触发一次
  var MODE_ONCE = 'once';

  // unique方式，函数不重复
  var MODE_UNIQUE = 'unique';

  // stopOnFalse方式，函数return false，停止以后的函数
  var MODE_STOPONFALSE = 'stopOnFalse';


  // 辅助方法：判断一项是否在数组内
  function inArray(array,item) {
    for(var i=0; i<array.length; i++) {
      if(array[i] === item) {
        return i;
      }
    }
    return -1;
  }

  var self = {
    // 添加函数，可以传入多个参数
    add: function() {
      var start = list.length;
      Xu.map(arguments, function(item,index) {
        if(typeof item === 'function') {
          if( option === MODE_UNIQUE && self.has(item) ) {
            return;
          }
          list.push(item);
        }
      })
      return this;
    },
    // 触发函数执行，传参是一个数组（可不传）
    // data = [,]: 第一个元素为函数的执行环境，第二个元素为函数的参数，是一个数组或空
    fire: function(data) {
      if(!list.length) {
        return;
      }
      data = data || [self,]
      //console.log(data[1])
      for(var i=0; i<list.length; i++) {
        
        if( list[i].apply(data[0],data[1]) === false && option === MODE_STOPONFALSE) {
          return;
        };
      }
      if( option === MODE_ONCE ) {
        list = [];
      }
      return this;
    },
    empty: function() {
      list = [];
      return this;
    },
    has: function(fn) {
      return fn ? inArray(list,fn)> -1 : !!(list && list.length);
    },
    remove: function(fn){
      if(!list.length) {
        return;
      }
      var index = inArray(list,fn);
      while(index >-1) {
        list.splice(index,1);
        index = inArray(list,fn);
      }
    }
  }

  return self;
  };


  // deferred
  Xu.Deferred = function() {
    /*成功或失败的回调函数*/
    var doneList = Xu.Callback('once');

    var failList = Xu.Callback('once');



    /*构建deferred对象*/
    var deferred = {

      resolve: function() {
        doneList.fire([window,arguments])
      },

      reject: function() {
        failList.fire([window,arguments])
      },

      then: function(doneFn,failFn) {
        deferred.done(doneFn).fail(failFn);
        return this;
      },

      done: function(doneFn) {
        doneList.add(doneFn);
        return this;
      },

      fail: function(failFn) {
        failList.add(failFn);
        return this;
      },
      always: function(fn) {
        deferred.done(fn).fail(fn);
        return this;
      }
    }
    return deferred;
  }

  // 队列queue
  Xu.Queue = function() {

    // 数据缓存对象
    var cache = {};

    var queueList = {
      // type默认是fx，是动画队列
      queue: function(type,data) {
        var args = arguments;
        //没有参数直接返回
        if(!args.length){
          return;
        }

        var q = null;
        // 只有一个参数并且是个函数
        if(args.length == 1 && typeof type === 'function') {
          data = type;
          type = 'fx';
        }

        q = cache[type] || [];

        // 添加缓存
        if( data instanceof Array) {
          q = data;
        }else {
          q.push(data)
        }
        cache[type] = q;

        //如果是动画队列并且没有开始的动画，执行第一个动画函数
        if(type == 'fx' && q.toString().indexOf('inprogress') === -1) {
          queueList.dequeue()
        }

        return q;

      },
      dequeue: function(type) {
        var fn, queue;
          type = type || 'fx';
          queue = cache[type];
          if(queue.length == 0 ) {
            return;
          }

          fn = queue.shift();

          if( fn === 'inprogress' ) {
            fn = queue.shift();
          }
          if( fn ) {
            if(type === 'fx') {
              queue.unshift('inprogress');
            }
            fn.call(null,function() {
              queueList.dequeue(type);
            })
          } 
      },
      // 延迟使用setTimeout来实现
      delay: function(type,timeout) {
        if(!type) {
          return;
        }
        if(arguments.length == 1) {
          timeout = type;
          type = 'fx';
        }

        if(typeof timeout == 'number') {
          var q = cache[type];
          if(!q) {
            q = cache[type] =  [_delay];
          }else {
            q.push(_delay)
          }

        }
        function _delay() {
          setTimeout(queueList.dequeue, timeout);
        }

        return this;

      },
      get: function(type) {
        type = type || 'fx';
        return cache[type];
      }
    }


    return queueList;
  }

  

  // animate部分
  Xu.fn.animate = function() {
     // 元素集合，如果是单一dom元素，用数组表示
    var i, 
      // 新建一个队列对象
      q = Xu.Queue(),

      // 获取元素css值
      _getStyle = function(elem,attr) {

        var value = window.getComputedStyle ? getComputedStyle(elem,null)[attr] : 
            elem.currentStyle[attr];
      
        if(attr == 'opacity') {
          value = (+value) * 100;
        }else {
          value = +value.replace(/pt|px/,'');
        }
        return value;
      },
      // 优化定时器
      requestNewAnimationFrame = window.requestAnimationFrame
        || window.webkitRequestAnimationFrame 
        || window.oRequestAnimationFrame 
        || window.mozRequestAnimationFrame 
        || window.msRequestAnimationFrame
        || window.setTimeout,
        
      cancelRequestNewAnimationFrame = window.cancelRequestAnimationFrame
        || window.cancelAnimationFrame
        || window.webkitCancelAnimationFrame
        || window.webkitCancelRequestAnimationFrame
        || window.mozCancelRequestAnimationFrame
        || window.oCancelRequestAnimationFrame
        || window.msCancelRequestAnimationFrame
        || clearTimeout;

    return function(options,time,callback) {
      // 获取所有元素
      var elems = this.getAll(),
        len = elems.length;

      // 将opacity转化为100制
      if(options.opacity && options.opacity <= 1) {
        options.opacity *= 100;
      }

      // 执行动画函数
      var _animate = function(next) {


        //属性， 目标值，原来的值，长度差
        var key, target, original, result, spaceLength;

        // 开始时间，当前时间，间隔时差
        var startTime = Xu.now(), nowTime, spaceTime;

        // 各个元素属性初始值设定
        var initValue = (function() {
          var initArr = [];
          for(i=0; i<len; i++) {
            for(key in options) {
              initArr[i+key] = _getStyle(elems[i],key);
            }

          }
          return initArr;
        })();

        // 循环执行函数
        var task = function() {
          // 动画完成指标
          var finded = true;

          nowTime = Xu.now();

          spaceTime = nowTime - startTime;

          for(i=0; i<len; i++) {
            var elem = elems[i];

            for(key in options) {

              target = options[key];

              original = initValue[i+key];

              spaceLength = target - original;

              if( spaceTime < time ) {
                finded = false;
                result = +(original + spaceTime/time * spaceLength).toFixed(2);
                //elem.style[key] = key == 'opacity' ? result/100 : result + 'px';
                if( key == 'opacity' ) {
                  elem.style[key] = result/100;
                  elem.style.filter = 'alpha(opacity='+result+')';
                }else {
                  elem.style[key] = result + 'px';
                }
              }else {
                //elem.style[key] = key == 'opacity' ? target/100 : target + 'px';
                if( key == 'opacity' ) {
                  elem.style[key] = target/100;
                  elem.style.filter = 'alpha(opacity='+target+')';
                }else {
                  elem.style[key] = target + 'px';
                }
              }


            }
          }

          if(finded) {

           // clearInterval(timerId);
            cancelRequestNewAnimationFrame(timerId)
            timerId = null;
            // 队列继续
            next();

            if(callback && typeof callback == 'function') {
              callback();
            }
          }else {
            timerId = requestNewAnimationFrame(task,15);
          }

        };

        //var timerId = setInterval(task,15);
        var timerId = requestNewAnimationFrame(task,15);

       }
       // 入队自动执行第一个队列内的函数
       q.queue(_animate);

       return this;
    }
  }()




  // ajax部分

  Xu.ajax = function() {
    //默认请求参数
    var _options = {
      url: null,
      type: 'GET',
      data: null,
      dataType: 'text',
      jsonp: 'callback',
      jsonpCallback: 'jsonpCallback',
      async: true,
      cache: true,
      timeout:null,
      contentType: 'application/x-www-form-urlencoded',
      success: null,
      error: null
    }

    //deferred模式
    var deferred = Xu.Deferred();

    // 私有继承
    // 第二个参数是默认对象，第一个参数是用户自定义对象。
    // 第一个对象没有的属性，将会使用第二个对象的值。
    var _extend = function(target,options) {
      if( typeof target !== 'object' || typeof options !== 'object' ) {
        return;
      }
      var copy ,clone, name;
      for( name in options ) {
        if(options.hasOwnProperty(name) && !target.hasOwnProperty(name)) {
          target[name] = options[name];
        }
      }
      return target;
    };

    // jsonp处理函数
    function sendJsonpRequest(url,callbackName,succCallback) {

      var script = document.createElement('script');

      script.type="text/javascript";
      script.src=url;

      document.body.appendChild(script);
      // 如果用户自己定义了回调函数，就用自己定义的，负责，调用success函数
      window[callbackName] = window[callbackName] || succCallback;

    }
    return function(options) {
      // 没有传参或者没有url，抛出错误
      if( !options || !options.url ) {
        throw('参数错误！');
      }
      //XMLHttpRequest传参无影响
      var xhr = new (window.XMLHttpRequest || ActiveXObject)('Microsoft.XMLHTTP');

      // 继承操作
      options.type = options.type.toUpperCase();
      _extend(options,_options);

      /*jsonp部分，直接返回*/
      if( options.dataType.toLowerCase() === 'jsonp' ) {
        var jsonpUrl = options.url.indexOf('?') > -1 ? options.url: options.url +
          '?' + options.jsonp+ '=' + options.jsonpCallback;

        sendJsonpRequest(jsonpUrl,options.jsonpCallback,options.success);
        
        return deferred;
      }

      // get搜索字符串
      var search = '';

      // 将data序列化
      var param= Xu.stringify(options.data)

      if( options.type === 'GET' ) {
        search = (options.url.indexOf('?') > -1 ? '&' : '?') + param;
        if(!options.cache) {
          search += '&radom='+Math.random();
        }
        
        param = null;
      }

      xhr.open( options.type, options.url + search, options.async );

      xhr.onreadystatechange = function() {
        if( xhr.readyState == 4 ) {
          if( xhr.status >= 200 && xhr.status < 300 || xhr.status == 304 ) {
            var text = xhr.responseText;
            // json格式转换
            if(options.dataType.toLowerCase() == 'json') {
                text = Xu.parseJSON(text)
            }
            // 成功后把success加入deferred
            if( typeof options.success === 'function') {

              deferred.done( options.success );
            }

            deferred.resolve(text,xhr.status);
            
          }else {
            // 失败后把error加入dererred
            if(typeof options.error === 'function') {
              deferred.fail(options.error);
            }

            deferred.reject('加载错误',500);
            
          }
        }
      }

      xhr.setRequestHeader('content-type',options.contentType);
      // get请求时param时null
      xhr.send(param);

      // 如果设置了超时，就定义
      if(typeof options.timeout === 'number') {
        // ie9+
        if( xhr.timeout ) {
          xhr.timeout = options.timeout;
        }else {
          setTimeout(function() {
            xhr.abort();
          },options.timeout)
        }
      }
      // 直接返回deferred
      return deferred;
    }
  }();

  Xu.extend({
    get: function(url,data,callback,type) {
      if(typeof data === 'function') {
        type = callback;
        callback = data;
        data = null;
      }
      if(typeof data === 'string') {
        type = data;
        data = null;
      }

      return Xu.ajax({
        url: url,
        data: data,
        type: 'GET',
        dataType: type || 'text',
        success: callback
      })
    },
    post: function(url,data,callback) {
      return Xu.ajax({
        url: url,
        data: data,
        type: 'post',
        success: callback
      })
    }
  })







  Xu.fn.init.prototype = Xu.fn;

  window.$ = window.Xu = Xu;


})(window,undefined);

